const { spawn } = require('child_process');
const fs = require('fs').promises;
const fsSync = require('fs');
const path = require('path');

const ROOT_DIR = path.resolve(__dirname, '../../../../'); // 回退到项目根目录

// 全局常量
const STATUS_FILE = path.resolve(ROOT_DIR, './upload-status.json');
const WORKER_SCRIPT = path.resolve(__dirname, './upload-worker.js');
const PRIVATE_KEY_CONFIG = path.join(ROOT_DIR, './privateKey/privateKey.json');
let isWorkerRunning = false; // 标记子进程是否在运行

// 主流程控制
const main = async () => {
	console.log('=== 小程序批量上传全流程启动 ===');

	try {
		await initStatusFile();
		const totalCount = await getTotalAppCount();
		console.log(`共发现 ${totalCount} 个小程序需要处理\n`);

		// 循环处理，失败也继续
		while (true) {
			const { hasUnprocessed, remainingCount } = await checkRemainingApps();
			if (!hasUnprocessed) {
				console.log('\n=== 所有小程序处理完毕 ===');
				await printFinalReport(); // 最终打印失败列表
				await cleanUp();
				break;
			}

			console.log(`剩余待处理小程序数量：${remainingCount}`);
			await spawnWorkerProcess(); // 启动子进程，失败不阻断
		}
	} catch (err) {
		console.log(err, 'err');
		console.error('\n❌ 全流程执行异常:', err.message);
		await printFinalReport(); // 异常时也打印已产生的失败列表
		await cleanUp();
		process.exit(1);
	}
};

// 初始化状态文件
const initStatusFile = async () => {
	if (!fsSync.existsSync(STATUS_FILE)) {
		await fs.writeFile(STATUS_FILE, JSON.stringify({
			processed: [], // 存储所有处理过的小程序（成功/失败）
			total: 0,
			lastUpdated: null
		}, null, 2));
	}
};

// 获取小程序总数量
const getTotalAppCount = async () => {
	const jsonData = await readPrivateConfig();
	const total = jsonData.appIds?.length || 0;

	const status = JSON.parse(await fs.readFile(STATUS_FILE, 'utf-8'));
	status.total = total;
	await fs.writeFile(STATUS_FILE, JSON.stringify(status, null, 2));

	return total;
};

// 检查剩余未处理的小程序
const checkRemainingApps = async () => {
	const status = JSON.parse(await fs.readFile(STATUS_FILE, 'utf-8'));
	const jsonData = await readPrivateConfig();
	const allApps = jsonData.appIds || [];

	const processedAppIds = status.processed.map(item => item.appid);
	const unprocessed = allApps.filter(app => !processedAppIds.includes(app.appid));

	return {
		hasUnprocessed: unprocessed.length > 0,
		remainingCount: unprocessed.length
	};
};

// 读取privateKey配置
const readPrivateConfig = async () => {
	if (!fsSync.existsSync(PRIVATE_KEY_CONFIG)) {
		throw new Error(`配置文件不存在：${PRIVATE_KEY_CONFIG}`);
	}
	const data = await fs.readFile(PRIVATE_KEY_CONFIG, 'utf-8');
	return JSON.parse(data);
};

// 启动子进程（核心：失败不阻断，继续循环）
const spawnWorkerProcess = async () => {
	return new Promise((resolve) => { // 不reject，确保流程继续
		isWorkerRunning = true;
		const workerEnv = {
			...process.env,
			STATUS_FILE,
			PRIVATE_KEY_CONFIG,
			ROOT_DIR,
		};

		// 启动子进程
		const worker = spawn(process.execPath, [WORKER_SCRIPT], {
			stdio: 'inherit',
			env: workerEnv,
			shell: false
		});

		// 子进程退出处理（成功/失败都继续）
		worker.on('exit', (code) => {
			isWorkerRunning = false;
			if (code === 0) {
				console.log('✅ 当前小程序处理完成，准备下一个...\n');
			} else {
				console.log('❌ 当前小程序处理失败，继续下一个...\n'); // 失败不阻断
			}
			resolve(); // 无论成功失败，都 resolve 继续循环
		});

		// 子进程启动失败处理
		worker.on('error', (err) => {
			isWorkerRunning = false;
			console.error('⚠️ 子进程启动失败:', err.message);
			console.log('继续处理下一个小程序...\n');
			resolve(); // 启动失败也继续
		});
	});
};

// 最终打印报告（核心：提取失败列表）
const printFinalReport = async () => {
	const status = JSON.parse(await fs.readFile(STATUS_FILE, 'utf-8'));
	const successList = status.processed.filter(item => item.status === 'success');
	const failList = status.processed.filter(item => item.status === 'fail');

	// 打印统计
	console.log('\n===== 处理结果统计 =====');
	console.log(`总数量：${status.total}`);
	console.log(`成功数量：${successList.length}`);
	console.log(`失败数量：${failList.length}`);

	// 打印失败列表（仅包含name和appid）
	if (failList.length > 0) {
		console.log('\n===== 失败小程序列表 =====');
		const formattedFailList = failList.map(item => ({
			name: item.name,
			appid: item.appid
		}));
		console.log(JSON.stringify(formattedFailList, null, 2)); // 格式化输出
	}
};

// 清理临时文件（可选）
const cleanUp = async () => {
	try {
		// 如需保留状态文件供后续查看，可删除以下代码
		if (fsSync.existsSync(STATUS_FILE)) {
			await fs.unlink(STATUS_FILE);
			console.log('\n已清理状态文件');
		}
	} catch (err) {
		console.warn('清理临时文件失败:', err.message);
	}
};

// 启动主流程
main();